﻿using System.Collections.Generic;
using ProjectDanmaku.Core;
using ProjectDanmaku.Entity;
using ProjectDanmaku.Entity.SubLayer.EnemyBullet;
using ProjectDanmaku.Scenario;
using ProjectDanmaku.Util;
using UnityEngine;
using UnityEngine.Serialization;

namespace ProjectDanmaku.Avatar.Reimu
{
    public class ReimuHomingCardBuletEntityData : EntityData
    {
        public Vector2 BaseVelocity;
        public float BaseRotation;
        public bool homing;
    }
    
    public class ReimuHomingCardBulletLayer : SimpleBulletSubLayer
    {
        [SerializeField] private AudioSource bulletDamageAudioSource;
        [SerializeField] private AudioClip bulletDamageAudioClip;
        [SerializeField] private GameObject deadCardPrefab;

        [FormerlySerializedAs("minTrackDistance")] [SerializeField] private float maxTrackDistance;

        private float _lastSoundPlayTime;

        private void OnEnable()
        {
            _shootableCollidePhysicsManipulator.OnHitCallback += OnHit;
        }

        private void OnDisable()
        {
            _shootableCollidePhysicsManipulator.OnHitCallback -= OnHit;
        }
        
        private bool FindNearestShootableObject(Vector2 pos, out Vector2 targetPos)
        {
            bool found = false;
            targetPos = Vector2.zero;
            float minDist = float.MaxValue;
            
            foreach (var shootableObject in DanmakuScenario.ShootableObjects)
            {
                var objPos = MathHelper.Vec3ToVec2(shootableObject.transform.position);
                if (CoordUtility.CheckOutOfScreen(objPos))
                    continue;
                
                var dist = (objPos - pos).sqrMagnitude;
                if (dist < minDist)
                {
                    minDist = dist;
                    targetPos = objPos;
                    found = true;
                }
            }

            return found;
        }

        private void PlayHitSound()
        {
            if (Time.time - _lastSoundPlayTime > 0.05f)
            {
                bulletDamageAudioSource.clip = bulletDamageAudioClip;
                bulletDamageAudioSource.Play();
                _lastSoundPlayTime = Time.time;
            }
        }

        private void OnHit(EntityData data)
        {
            PlayHitSound();
            
            Destroy(
                Instantiate(
                    deadCardPrefab, data.Position, Quaternion.Euler(0, 0, data.RotateZ * Mathf.Rad2Deg)), 1f);
        }
        
        protected override void EntityLogicTick(EntityData data)
        {
            data.tick += Time.deltaTime;
            
            ReimuHomingCardBuletEntityData rData = (ReimuHomingCardBuletEntityData)data;
            var pos = data.Position;
            
            if (rData.homing && FindNearestShootableObject(data.Position, out Vector2 targetPos))
            {
                var blend = data.tick / 0.3f;
                
                data.RotateZ = MathHelper.Vec2ToRotateY(data.Velocity) + (Mathf.PI / 2f);

                var targetV = rData.BaseVelocity.magnitude * (targetPos - pos).normalized;
                var baseV = rData.BaseVelocity;
                
                data.Velocity = Vector2.Lerp(baseV, targetV, blend);
                
                base.EntityLogicTick(data);
            }
            else
            {
                base.EntityLogicTick(data);
            }
        }

        protected override void EntityInit(EntityData data)
        {
            if (data is ReimuHomingCardBuletEntityData rData)
            {
                FindNearestShootableObject(rData.Position, out var targetPos);
                if ((targetPos - data.Position).magnitude < maxTrackDistance)
                {
                    rData.homing = true;
                }
            }
        }
    }
}